package com.iwhalecloud.uncc.utils;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.exception.ExceptionUtils;


import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.lang.management.ManagementFactory;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Enumeration;
import java.util.UUID;

@Slf4j
public class AppInfoUtil {
	private static final String CLOUD_NODE_ID = "CLOUD_NODE_ID";
	private static final Object containerLock = new Object();
	private static String containerId;

	private AppInfoUtil() {
	}

	/**
	 * 节点ID/容器ID
	 */
	public static String getContainerId() {
		if (StringUtils.isEmpty(containerId)) {
			synchronized (containerLock) {
				if (StringUtils.isEmpty(containerId)) {
					containerId = System.getProperty(CLOUD_NODE_ID);
					if (StringUtils.isEmpty(containerId)) {
						containerId = System.getenv(CLOUD_NODE_ID);
					}
					if (StringUtils.isEmpty(containerId)) {
						containerId = getFileContainerId();
					}
					if (StringUtils.isEmpty(containerId)) {
						containerId = String.format("%s", getPId());
					}
					if (StringUtils.isEmpty(containerId)) {// 用uuid代替
						containerId = UUID.randomUUID().toString().replaceAll("-", "");
					}
				}
			}
		}
		return containerId;
	}

	/**
	 * 从docker文件获取容器节点Id
	 */
	private static String getFileContainerId() {
		String tmpInfo = null;
		// 从容器中该文件/proc/1/cpuset中获取
		String pathName = "/proc/1/cpuset";
		File file = new File(pathName);
		if (file.exists()) {
			try {
				/* /docker/e5b0cf0b9180780305f5aab4e886c14d1d676d6b9468a70f1399827f8dc3dc76 */
				String fileContent = FileUtils.readFileToString(file);
				if (!fileContent.isEmpty()) {
					String[] fileContents = fileContent.split("/");
					if (fileContents[fileContents.length - 1].length() >= 12) {
						tmpInfo = fileContents[fileContents.length - 1];
						return tmpInfo.replace("\n", "");
					}
				}
			} catch (Exception e) {
				tmpInfo = null;
			}
		}
		return tmpInfo;
	}

	/**
	 * PID
	 */
	private static String getPId() {
		try {
			String name = ManagementFactory.getRuntimeMXBean().getName();
			int idx = name.indexOf('@');
			return idx > 0 ? name.substring(0, idx) : "-1";
		} catch (Exception ignored) {
			return "-1";
		}
	}

	public static boolean isWindows() {
		return System.getProperties().getProperty("os.name").toUpperCase().contains("WINDOWS");
	}


	public static String getDiskUse(String diskPath) throws Exception {
		File file = new File(diskPath);
		Long total = file.getTotalSpace();
		Long usable = file.getUsableSpace();
		double used = (total.doubleValue() - usable.doubleValue()) / 1024 / 1024 / 1024;
		BigDecimal bd = new BigDecimal(used);
		return bd.setScale(2, RoundingMode.HALF_UP).doubleValue() + "G";
	}

	public static double getDiskUseRate(String diskPath) throws Exception {
		File file = new File(diskPath);
		Long total = file.getTotalSpace();
		Long usable = file.getUsableSpace();
		double used = total.doubleValue() - usable.doubleValue();
		double rate = used / total.doubleValue();
		BigDecimal bd = new BigDecimal(rate);
		return bd.setScale(2, RoundingMode.HALF_UP).doubleValue();
	}

	public static String getDiskUseByCommand() throws Exception {
		String use = null;
		if (!isWindows()) {
			String cmd = "df -h /";
			String result = command(cmd);
			String[] data = result.replace("\n", " ").split(" +");
			use = data[8];
		}
		return use;
	}

	public static double getDiskUseRateByCommand() throws Exception {
		double rate = 0;
		if (!isWindows()) {
			String cmd = "df -h /";
			String result = command(cmd);
			String[] data = result.replace("\n", " ").split(" +");
			rate = Double.parseDouble(data[10].replace("%", "")) / 100;
		}

		return rate;
	}

	public static String command(String command) {
		StringBuilder sb = new StringBuilder();
		InputStreamReader isReader = null;
		try {
			Process process = Runtime.getRuntime().exec(command);
			process.waitFor();
			new InputStreamReader(process.getInputStream());
			LineNumberReader lineReader = new LineNumberReader(isReader);
			String line = null;
			while ((line = lineReader.readLine()) != null) {
				sb.append(line).append("\n");
			}
		} catch (Exception e) {
			log.error(ExceptionUtils.getStackTrace(e));
		} finally {
			if (isReader != null) {
				try {
					isReader.close();
				} catch (IOException e) {
					log.error(ExceptionUtils.getStackTrace(e));
				}
			}
		}
		return sb.toString();
	}

	public static String getRealIp() throws SocketException {
		String localip = null;// 本地IP，如果没有配置外网IP则返回它
		String netip = null;// 外网IP

		Enumeration<NetworkInterface> netInterfaces = NetworkInterface.getNetworkInterfaces();
		InetAddress ip = null;
		boolean finded = false;// 是否找到外网IP
		while (netInterfaces.hasMoreElements() && !finded) {
			NetworkInterface ni = netInterfaces.nextElement();
			Enumeration<InetAddress> address = ni.getInetAddresses();
			while (address.hasMoreElements()) {
				ip = address.nextElement();
				if (!ip.isSiteLocalAddress() && !ip.isLoopbackAddress() && ip.getHostAddress().indexOf(":") == -1) {// 外网IP
					netip = ip.getHostAddress();
					finded = true;
					break;
				} else if (ip.isSiteLocalAddress() && !ip.isLoopbackAddress()
						&& ip.getHostAddress().indexOf(":") == -1) {// 内网IP
					localip = ip.getHostAddress();
				}
			}
		}

		if (netip != null && !"".equals(netip)) {
			return netip;
		} else {
			return localip;
		}
	}
}